package com.cysoft;

import com.cysoft.config.ApsPlanningDBConfig;
import com.cysoft.domain.*;
import com.cysoft.service.MachineService;
import com.cysoft.service.MoldService;
import com.cysoft.service.TaskService;
import com.cysoft.service.WheelService;
import com.cysoft.utils.StreamUtil;
import org.optaplanner.core.api.solver.Solver;
import org.optaplanner.core.api.solver.SolverFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.util.StopWatch;

import java.io.File;
import java.util.List;

public class App {

    public static void main(String[] args) {

        boolean testData = false;
        StopWatch watch = new StopWatch();
        watch.start("Build Solver");
        //通过配置的xml文件，构造求解器
        SolverFactory<TaskSolution> solverFactory = SolverFactory.createFromXmlResource(
                "com/cysoft/taskassignmentConfiguration.xml");
        Solver<TaskSolution> solver = solverFactory.buildSolver();
        System.out.println("通过配置的xml文件，构造好了求解器");
        watch.stop();

        //这里将初始数据从数据库载入
        watch.start("Load Data");
        TaskSolution unsolvedApsSolution = getUnassignment();
        watch.stop();
        System.out.println("将初始数据从数据库载入");
//        if(testData) {
//            List<Task> taskList = unsolvedApsSolution.getTaskList();
//            List<Machine> machineList = unsolvedApsSolution.getMachineList();
//
//            for (Machine machine:machineList                 ) {
//                System.out.println(machine.getId() + "  ==>  "+machine.getName());
//            }
//            System.out.println("===============================");
//
//            for (Task task:taskList                 ) {
//                System.out.println(task.getId() + "  ==>  "+task.getWheel().getWheelCode());
//            }
//            return;
//        }
        //启动引擎求解问题
        watch.start("Solve solution");
        TaskSolution solvedCloudBalance = solver.solve(unsolvedApsSolution);
        System.out.println("通过引擎求解问题");
        watch.stop();

        //输出每个bom节点分配的设备
        System.out.println(
                "\nSolved apsPlanning:\n"
                        + "求解结果为:\n"
                        + toDisplayCsv(solvedCloudBalance));

        System.out.println("最后分数为：" + solvedCloudBalance.getScore());
//        System.out.println("最后分数为：" + toDisplayTaskList(solvedCloudBalance));

        System.out.println(watch.prettyPrint());
    }

    //输出每个bom节点分配的设备
    public static String toDisplayString(TaskSolution apsPlanningSolution) {
        //新建一个StringBuilder，相对于String的好处是可以持续增加字符串长度而不用重新分配空间
        StringBuilder displayString = new StringBuilder();
        //遍历bomTask节点，获取到给每个bom节点分配的机器
        for (Task task : apsPlanningSolution.getTaskList()) {
            Machine device = task.getMachine();
            //然后将分配的机器输出
            if(task.getBeginDateTime() != null && task.getEndDateTime() != null) {
                displayString.append("  ")
                        .append("轮型[" + task.getWheelCode())
                        .append("] ,生产[")
                        .append(task.getCount())
                        .append("] ,铸造台[")
                        .append(device == null ? null : device.getName()).append("] ")
                        .append("] ,生产[")
                        .append(task.getCount())
                        .append("] ,模具产能[")
                        .append(60/task.getWheel().getCostTime())
                        .append("] ")
                ;
            }
            if(task.getBeginDateTime() != null){
                displayString.append(" ,开始生产时间：").append(task.getBeginDateTime().toString());
            }
            if(task.getEndDateTime() != null) {
                displayString.append(" ,结束生产时间：").append(task.getEndDateTime().toString());
            }
            displayString.append(" ,纤维网&铁网：").append(task.getWheel().getFilterTypeStr());
            displayString.append("\n");

        }
        return displayString.toString();
    }

    public static String toDisplayCsv(TaskSolution apsPlanningSolution) {
        //新建一个StringBuilder，相对于String的好处是可以持续增加字符串长度而不用重新分配空间
        StringBuilder displayString = new StringBuilder();
        //遍历bomTask节点，获取到给每个bom节点分配的机器
        for (Task task : apsPlanningSolution.getTaskList()) {
            Machine device = task.getMachine();
            //然后将分配的机器输出
            if(task.getBeginDateTime() != null && task.getEndDateTime() != null && task.getMold() != null) {
                displayString.append("  ")
                        .append(task.getWheelCode())
                        .append(",")
                        .append(task.getCount())
                        .append(",")
                        .append(device == null ? "" : device.getName())
                        .append(",")
                        .append(task.getMold().getId())
                        .append(",")
                        .append(task.getMold().getName())
                        .append(",")
                        .append(task.getCount())
                        .append(",")
                        .append(60/task.getWheel().getCostTime())
                        .append(",")
                        .append(task.getWheel().getCostTime())
                        .append(",")
                        .append(task.getPaymentTime().toString())
                        .append(",")
                        .append(task.getBeginDateTime().toString())
                        .append(",")
                        .append(task.getEndDateTime().toString())
                        .append(",")
                        .append(task.getWheel().getFilterTypeStr())
                ;
            } else {
                displayString.append("  ")
                        .append(task.getWheelCode())
                        .append(",")
                        .append(task.getCount())
                        .append(",")
                        .append(device == null ? "" : device.getName())
                        .append(",")
//                        .append(task.getMold().getName())
                        .append("  #####  时间规划异常 #####");
            }
            displayString.append("\n");

        }
        return displayString.toString();
    }


    public static MachineService machineService;
    public static MoldService moldService;
    public static TaskService taskService;
    public static WheelService wheelService;
    //从数据库获取到computer和process的初始数据填入solution中
    protected static TaskSolution getUnassignment() {

        ApplicationContext context =
                new AnnotationConfigApplicationContext(ApsPlanningDBConfig.class);

        machineService = context.getBean("machineService", MachineService.class);
        moldService = context.getBean("moldService", MoldService.class);
        taskService = context.getBean("taskService", TaskService.class);
        wheelService = context.getBean("wheelService", WheelService.class);

        File machineListFile = new File(App.class.getClass().getResource("/data/machineListFile.txt").getFile());
        File moldListFile = new File(App.class.getClass().getResource("/data/moldListFile.txt").getFile());
        File bomTaskListFile = new File(App.class.getClass().getResource("/data/bomTaskListFile.txt").getFile());
        File wheelListFile = new File(App.class.getClass().getResource("/data/wheelListFile.txt").getFile());

        List<Machine> machineList = StreamUtil.readList(machineListFile);
        List<Mold> moldList = StreamUtil.readList(moldListFile);
        List<Task> bomTaskList = StreamUtil.readList(bomTaskListFile);
        List<Wheel> wheelList = StreamUtil.readList(wheelListFile);

        if(machineList == null) {
            machineList = machineService.getDeviceList();
            StreamUtil.writeObject(machineList,machineListFile);
        }
        if(moldList == null) {
            moldList = moldService.getMoldList();
            StreamUtil.writeObject(moldList,moldListFile);
        }
        if(bomTaskList == null) {
            bomTaskList = taskService.getBomTaskList();
            StreamUtil.writeObject(bomTaskList,bomTaskListFile);
        }
        if(wheelList == null) {
            wheelList = wheelService.getWheelList();
            StreamUtil.writeObject(wheelList,wheelListFile);
        }

        TaskSolution unAssignment = new TaskSolution(machineList, wheelList, moldList,bomTaskList);


        return unAssignment;
    }

}